package org.pb.core;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.font.TextAttribute;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;


public class ImagePainter {
	
	private static final Logger logger = Logger.getLogger(ImagePainter.class);
	
	private double charInitX = 0;
	private double charInitY = 0;
	private int nextPlacardIncrementX = 0;
	private int nextPlacardIncrementY = 0;
	private int nextLinePlacardIncrementX = 0;
	private int nextLinePlacardIncrementY = 0;
	private int imgWidth = 0;
	private int imgHeight = 0;
	
	private Configuration config;
	private FileAccessor fileAccessor;
	private PlacardBoy[][] boys = null;
	
	public static void main(String[] args){
		
		ImagePainter painter = new ImagePainter();
		//painter.test();
		painter.paint("表白神器握在手，不怕没有女朋友。");
		//painter.paint("我爱你，I Love You，Je t’aime，爱している");
		
	}
	
	public ImagePainter(){
		
		this.config = new Configuration();
		this.fileAccessor = new FileAccessor(config);
		
	}
	
	private void paint(String str){
		
		int rowCount = prepareBoys(str);
		if(rowCount < 1){
			throw new RuntimeException("行数为0，程序结束");
		}
		if(this.boys == null || this.boys.length == 0){
			throw new RuntimeException("boys为空或boy数量为0，程序结束");
		}
		
		logger.debug("行数是"+rowCount);
		
		calculateBoyPosition(rowCount);
		paintImage(rowCount);
		
	}
	
	private Image paintSingleBoy(String character,Image boyImg){
		
		if(character.length() != 1){
			throw new PaintingException("只允许打印一个字符");
		}
		
		Image result = null;
		
		if(boyImg != null && config != null){
			
			int fontSize = config.getFontSize();
			
			if(charInitX == 0 || charInitY == 0){
				calculateCharInitXY2(config.getPlacardCenterX(),
						config.getPlacardCenterY(),
						config.getPlacardRotateDegree(),
						config.getPlacardShearInnerDegree(),
						fontSize);
			}
			
			
			int boyImgWidth = boyImg.getWidth(null);
			int boyImgHeight = boyImg.getHeight(null);
			
			AffineTransform at = new AffineTransform();
			if(charInitX > 0 && charInitY > 0){
				at.translate(charInitX, charInitY);
				at.rotate(Math.toRadians(config.getPlacardRotateDegree()));
				at.shear(-Math.tan(Math.toRadians(90-config.getPlacardShearInnerDegree())), 0);
			}
			
			BufferedImage boyBufImg = new BufferedImage(boyImgWidth,boyImgHeight,BufferedImage.TYPE_INT_ARGB);
			Graphics2D boyG = boyBufImg.createGraphics();
			
			boyG.drawImage(boyImg, 0, 0, boyImgWidth, boyImgHeight, null);
			
			
			Font font = new Font("微软雅黑",Font.PLAIN,fontSize);
			
			boyG.setFont(font);
			boyG.setColor(Color.RED);
			boyG.setTransform(at);
			boyG.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);//字体边缘模糊（羽化）
			boyG.drawString(character, 0, fontSize - config.getFontBottomMargin());
			//boyG.drawString(character, 0, fontSize);
			
			boyG.dispose();
			
			result =  boyBufImg;
			
		}
		
		return result;
		
	}
	
	/*
	private void calculateCharInitXY(int placardCenterX,int placardCenterY,double placardRotateDegree,double placardShearDegree,int fontSize){
		
		double gama = (360 - 2*placardShearDegree)/4;
		double theta = 90 - placardRotateDegree - (gama);
		double c = Math.cos(Math.toRadians(gama))*fontSize;
		double a = Math.cos(Math.toRadians(theta))*c;
		double b = Math.sin(Math.toRadians(theta))*c;
		this.charInitX = placardCenterX - rounding(b);
		this.charInitY = placardCenterY - rounding(a);
		
		logger.debug("CharInitXY is "+this.charInitX+","+this.charInitY);
		
		
	}*/
	
	private void calculateCharInitXY2(double placardCenterX,double placardCenterY,double placardRotateDegree,double placardShearDegree,int fontSize){
		
		//double r1 = fontSize/Math.sin(Math.toRadians(placardShearDegree));
		double r2 = fontSize/Math.tan(Math.toRadians(placardShearDegree));
		double t = fontSize - r2;
		double c = Math.sqrt((fontSize*fontSize)+t*t)/2;
		double gama = Math.toDegrees(Math.asin(t/(2*c)));
		
		double theta = gama - placardRotateDegree;
		double a = Math.cos(Math.toRadians(theta))*c;
		double b = Math.sin(Math.toRadians(theta))*c;
		this.charInitX = placardCenterX - rounding(b);
		this.charInitY = placardCenterY - rounding(a);
		
		logger.debug("CharInitXY is "+this.charInitX+","+this.charInitY);
		
	}
	
	/**
	 * 四舍五入
	 * 
	 * @param value
	 * @return
	 */
	private int rounding(double value){
		
		BigDecimal bd = new BigDecimal(value).setScale(0, BigDecimal.ROUND_HALF_UP);
		return bd.intValue();
		
		
	}
	
	private int prepareBoys(String content){
		
		if(content.length() == 0 || content == null){
			return 0;
		}

		TemplateGenerator templateGen = new TemplateGenerator(fileAccessor);
		
		int maxChar = config.getMaxChar();
		int rowLength = config.getRowLength();
		

		boys = new PlacardBoy[maxChar/rowLength][rowLength];
		
		//以空格进行分词
		//String[] words = splitWordAndSpace(content);
		//以空格及标点符号分词
		String[] words = splitWord(content);
		
		logger.debug("分词后："+Arrays.toString(words));
		
		int i;
		int used = 0;
		int rowNumber = 0;
		String preWord = "";
		for(i=0;i<words.length;i++){
			
			
			String word = words[i];
			
			int wordLength = word.length();
			
			logger.debug("rowLength = "+rowLength+",wordLength = "+wordLength+",used = "+used);
			
			
			//词长度小于行长度，且词长度大于行剩余空间，且前一个人词是空格，换行
			if(wordLength < rowLength && wordLength > rowLength - used && " ".equals(preWord)){
				used = 0;
				rowNumber++;
			}
			/*if(wordLength < rowLength && wordLength > rowLength - used ){
				//System.out.println("换行");
				used = 0;
				rowNumber++;
			}*/
			
			for(int j=0;j<word.length();j++){
				String c = String.valueOf(word.charAt(j));
				Image imgTemplate = templateGen.getPlacardBoyTemplate();
				Image img = paintSingleBoy(c,imgTemplate);
				PlacardBoy boy = new PlacardBoy(c);
				boy.setBoyImage(img);
				boys[rowNumber][used] = boy;
				
				used++;
				//换行
				if(used == rowLength){
					used = 0;
					rowNumber++;
				}
			}
			
			preWord = word;
			
		}
		
		return rowNumber+1;		//行数
	}
	
	
	
	protected void calculateBoyPosition(int rowCount){
		
		if(rowCount < 1 || this.boys == null){
			return;
		}
		
		calculateBoyPositionIncrement();
		
		int rowLength = config.getRowLength();
		
		PlacardBoy ppb = null;
		int margin = config.getMargin();
		int x = margin, y = margin;
		int currentX = 0,currentY = 0;
		for(int r = 0 ; r < rowCount ; r++){
			int startX = x + this.nextLinePlacardIncrementX*(rowCount-1-r);
			int startY = y + this.nextLinePlacardIncrementY*r;
			
			for(int c=0 ; c < rowLength ; c++){
				//设置最终图的宽度
				if(r == 0 && c == rowLength - 1){
					int boyImgWidth = config.getBoyImgWidth();
					this.imgWidth = startX + (this.nextLinePlacardIncrementX * (rowLength - 1)) + boyImgWidth + margin;
				}
				//设置最终图的高度
				if(r == rowCount - 1 && c == rowLength - 1){
					this.imgHeight = startY + (this.nextLinePlacardIncrementY * rowLength) + margin;
				}
				
				PlacardBoy pb = boys[r][c];
				
				if(pb == null){
					continue;
				}
				if(ppb == null){
					pb.setXY(startX, startY);
				}else{
					currentX = ppb.getX()+this.nextPlacardIncrementX;
					currentY = ppb.getY()+this.nextPlacardIncrementY;
					pb.setXY(currentX, currentY);
				}
				ppb = pb;
			}
			ppb = null;
		}
		
		logger.info("图片大小为："+this.imgWidth+"px , "+this.imgHeight+"px");
		
		
	}
	
	private void calculateBoyPositionIncrement(){
		
		double afa = config.getPlacardRotateDegree();
		double beta = config.getPlacardShearInnerDegree();
		double d1 = config.getPlacardHorizontalDistance();
		double d2 = config.getPlacardVerticalDistance();
		double x1 = config.getPlacardCenterX();
		double y1 = config.getPlacardCenterY();
		double x2 = config.getPlacardLeftTopCornerX();
		double y2 = config.getPlacardLeftBottomCornerY();
		double x3 = config.getBoyImgWidth() - x1;
		
		double e = x1 - x2;
		double dx = Math.cos(Math.toRadians(afa))*d1;
		double a = x3 + dx + e;
		
		this.nextPlacardIncrementX = rounding(a);
		this.nextPlacardIncrementY = rounding(Math.tan(Math.toRadians(afa))*a);
		
		double f = y2 - y1;
		double gama = 180 - ((360-2*beta)/2) - afa;
		double dy = Math.sin(Math.toRadians(gama)) * d2;
		double m = f + dy + y1;
		
		this.nextLinePlacardIncrementX = rounding(m/Math.tan(Math.toRadians(gama)));
		this.nextLinePlacardIncrementY = rounding(m);
		
		
		
		logger.debug("nextPlacardIncrementX is "+this.nextPlacardIncrementX);
		logger.debug("nextPlacardIncrementY is "+this.nextPlacardIncrementY);
		logger.debug("nextLinePlacardIncrementX is "+this.nextLinePlacardIncrementX);
		logger.debug("nextLinePlacardIncrementY is "+this.nextLinePlacardIncrementY);
		
		
		
	}
	
	public void paintImage(int rowCount){
		
		if(this.boys == null || this.boys.length == 0){
			throw new RuntimeException("boys为空或boy数量为0，程序结束");
		}
		if(this.imgHeight == 0 || this.imgWidth == 0){
			throw new IllegalArgumentException("imgHeigth和imgWidth不能为0");
		}
		
		BufferedImage mainImg = new BufferedImage(this.imgWidth,this.imgHeight,BufferedImage.TYPE_INT_ARGB);
		Graphics2D mainImgG = mainImg.createGraphics();
		
		
		int rowLength = config.getRowLength();
		for(int r = 0;r<rowCount;r++){
			
			for(int c = 0;c<rowLength;c++){
				
				PlacardBoy b = boys[r][c];
				Image boyImg = null;
				if(b != null && (boyImg = b.getBoyImage()) != null){
					//System.out.println(b);
					int boyImgWidth = boyImg.getWidth(null);
					int boyImgHeight = boyImg.getHeight(null);
					mainImgG.drawImage(boyImg, b.getX(), b.getY(), boyImgWidth, boyImgHeight, null);
				}
				
			}
		}
		
		mainImgG.dispose();
		
		fileAccessor.saveImageToFile(mainImg,config.getOutputName());
		
	}
	
	/**
	 * 
	 * 以空格分割单词，返回单词及空格
	 * 
	 * @param text
	 * @return 
	 */
	@Deprecated
	private String[] splitWordAndSpace(String text){
		
		text = text.trim();
		String[] words = text.split("\\s");
		
		System.out.println(words.length);
		if(words.length == 1){
			return words;
		}
		int wordsNumber = words.length;
		int spaceNumber = wordsNumber - 1;
		String[] result = new String[wordsNumber+spaceNumber];
		int used=0;
		for(int i=0;i<wordsNumber;i++){
			result[used] = words[i];
			if(used < result.length - 1){
				result[++used] = " ";
			}
			used++;
		}
		return result;
		
	}
	
	/**
	 * 
	 * 以空格和逗号句号分好分割单词，返回单词及对应标点符号
	 * 
	 * @param text
	 * @return 
	 */
	private String[] splitWord(String text){
		
		text = text.trim();
		
		Pattern p = Pattern.compile(",| |\\.|，|。|'|’");
		//Pattern p = Pattern.compile(" ");
		StringBuilder tempWord = new StringBuilder();
		List<String> tempResult = new ArrayList<String>();
		for(int i = 0;i< text.length();i++){
			char c = text.charAt(i);
			String s = String.valueOf(c);
			if((p.matcher(s)).matches()){
				tempResult.add(tempWord.toString());
				tempResult.add(s);
				tempWord.delete(0, tempWord.length());
				
			}else{
				tempWord.append(s);
			}
		}
		if(tempWord.length()>0){
			tempResult.add(tempWord.toString());
		}
		System.out.println(tempResult);
		String[] sa = new String[tempResult.size()];
		sa = tempResult.toArray(sa);
		
		return sa;
		
		
	}
	
	public void test(){
		
		Image img = fileAccessor.getFileImage("image/btest.png");
		int imgW = img.getWidth(null);
		int imgH = img.getHeight(null);
		BufferedImage mainImg = new BufferedImage(imgW,imgH,BufferedImage.TYPE_INT_ARGB);
		Graphics2D boyG = mainImg.createGraphics();
		boyG.drawImage(img, 0, 0, imgW, imgH, null);
		
		//字符基线
		boyG.setPaint(Color.blue);
		boyG.drawLine(1, 40, 160, 40);
		
		AffineTransform at1 = new AffineTransform();
		at1.translate(20, 10);
		//at1.rotate(Math.toRadians(24));
		at1.shear(-Math.tan(Math.toRadians(30)), 0);

		//字符空间
		boyG.setTransform(at1);
		boyG.setPaint(Color.green);
		boyG.drawRect(0, 0, 20, 36);
		boyG.setTransform(at1);
		boyG.setPaint(Color.green);
		boyG.drawRect(90, 0, 30, 36);
		
		int fontSize = 30;
		Font font = new Font("微软雅黑",Font.PLAIN,fontSize);
		boyG.setFont(font);
		boyG.setColor(Color.RED);
		boyG.setBackground(Color.yellow);
		boyG.setTransform(at1);
		boyG.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);//字体边缘模糊（羽化）
		boyG.drawString("apple 苹果", 0, fontSize);
		
		boyG.dispose();
		
		fileAccessor.saveImageToFile(mainImg, "test.png");
		
	}


}
